# -*- coding:utf-8 -*-

from abc import ABCMeta, abstractmethod


class Section(metaclass=ABCMeta):
    @abstractmethod
    def describe(self):
        pass


class PersonalSection(Section):
    def describe(self):
        print ('Personal Section')


class AlbumSection(Section):
    def describe(self):
        print ('Album Section')


class PatentSection(Section):
    def describe(self):
        print ('Patent Section')


class PublicationSection(Section):
    def describe(self):
        print ('Publication Section')


class Profile(metaclass=ABCMeta):
    def __init__(self):
        self.sections = []
        self.create_profile()

    @abstractmethod
    def create_profile(self):
        pass

    def get_sections(self):
        return self.sections

    def add_sections(self, section):
        self.sections.append(section)


class LinkedIn(Profile):
    def create_profile(self):
        self.add_sections(PersonalSection())
        self.add_sections(PatentSection())
        self.add_sections(PublicationSection())


class Facebook(Profile):
    def create_profile(self):
        self.add_sections(PersonalSection())
        self.add_sections(AlbumSection())


if __name__ == '__main__':
    profile_type = input('LinkedIn or Facebook?')
    profile = eval(profile_type)()
    print ('creating profile..', type(profile).__name__)
    print ('profile has section --', profile.get_sections())

# 抽象类, 是从一堆类中抽象出来的, 比如上面的三个类可以抽取出动物类
#
# 抽象类的特点是不能给实例化, 只能被子类继承, 由子类实现了父类的抽象方法后, 子类才能被实例化
#
# Python中的接口, 抽象类, 抽象函数
# Python中的接口是个弱概念, 从Java中的概念延伸而来, Python中通过抽象类和抽象方法来实现一个接口, 例如Python3中, class 类继承的 abc.ABC 即为抽象类, @abstractmethod 装饰器使其装饰的函数成为抽象函数
#
# 一般情况下, Python多在单继承的情况下使用抽象类